package cn.gjxblog.core.captcha;


import cn.gjxblog.core.captcha.img.ImgCaptcha;
import cn.gjxblog.core.captcha.sms.SmsCapthcha;
import cn.gjxblog.core.properties.SecurityProperties;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author gjx
 * @version v1.0
 * @Description 验证码过滤器
 * @date 2019/1/16 14:35
 */
public class SmsCaptchaSecurityFilter extends OncePerRequestFilter implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(SmsCaptchaSecurityFilter.class);

    private AuthenticationFailureHandler authenticationFailureHandler;

    private SecurityProperties securityProperties;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    private Set<String> uris = new HashSet<>();
    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        String[] strings = StringUtils.splitByWholeSeparatorPreserveAllTokens(securityProperties.getCaptcha().getSms().getUri(), ",");
       if(strings !=null){
           Arrays.stream(strings).forEach(s -> uris.add(s));
       }
        uris.add("/login/mobile");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        boolean flag = false;
        for (String uri : uris) {
            if(antPathMatcher.match(request.getRequestURI(),uri)){
                flag=true;
                break;
            }
        }

       if(flag){
            //校验验证码
            try {
                validate(request);
            } catch (CaptchaException e) {
                authenticationFailureHandler.onAuthenticationFailure(request,response,e);
                return;
            }
        }

        doFilter(request,response,filterChain);
    }

    private void validate(HttpServletRequest request) {
        logger.info("开始校验验证码");
        //获取验证码
        String codeInRequest = request.getParameter("captcha");
        HttpSession session = request.getSession();
        SmsCapthcha codeInSession = (SmsCapthcha)session.getAttribute(CaptchaController.ssession_key);


        if (StringUtils.isBlank(codeInRequest)) {
            throw new CaptchaException("请填写验证码");
        }

        if (codeInSession == null) {
            throw new CaptchaException( "验证码不存在");
        }

        if (codeInSession.isExpried()) {
            session.removeAttribute(CaptchaController.ssession_key);
            throw new CaptchaException("验证码已过期，请重新获取");
        }

        if (!StringUtils.equals(codeInSession.getCode(), codeInRequest)) {
            throw new CaptchaException("验证码不正确");
        }

        session.removeAttribute(CaptchaController.ssession_key);

    }

    public void setSecurityProperties(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }
}
